package com.example.demo.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.example.demo.entity.Dup;
import com.example.demo.extra.PageRequest;
import com.example.demo.service.DupService;
import org.apache.ibatis.cursor.Cursor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author long
 * @version 1.0.0
 * @ClassName TestController
 * @Description TODO
 * @createTime 2022.03.14 16:35
 */
@Controller
@RequestMapping("/test")
public class TestController {

    Logger logger = LoggerFactory.getLogger(TestController.class);

    @Autowired
    private DupService dupService;

    @GetMapping("/test")
    public String index() {
        logger.info("index");
        return "index";
    }

    @GetMapping("/download/{type}")
    @Transactional(rollbackFor = Exception.class)
    public void download(HttpServletResponse httpServletResponse, @PathVariable String type) throws IOException {
//        httpServletResponse.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        httpServletResponse.setContentType("application/application/octet-stream");
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setHeader("Content-disposition", "attachment;filename*=utf-8''" + System.currentTimeMillis() + ".zip");
//        Iterable<Dup> dups ;
//        if ("0".equals(type)){
//            dups = dupService.streamQuery(1000000);
//        }else {
//            dups = dupService.queryByPage(new PageRequest(1, 1000000));
//        }

        //记录文件名称
        List<String> names = new ArrayList<>();
        for (int i = 1; i <= 20; i++) {
            List<Dup> dups = dupService.queryByPage(new PageRequest(i, 500000));
            String excelName = "C:\\Users\\long\\Desktop\\file\\" + System.currentTimeMillis() + ".xlsx";
            names.add(excelName);
            List<Dup> dupList = new ArrayList<>();
            AtomicInteger count = new AtomicInteger();
            ExcelWriter excelWriter = EasyExcel.write(excelName, Dup.class).build();
            try {
                dups.forEach(dup -> {
                    dupList.add(dup);
                    if (dupList.size() >= 50000) {
                        WriteSheet writeSheet = EasyExcel.writerSheet("导出" + count.getAndIncrement()).build();
                        excelWriter.write(dupList, writeSheet);
                        dupList.clear();
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                // 千万别忘记finish 会帮忙关闭流
                if (excelWriter != null) {
                    excelWriter.finish();
                    dupList.clear();
                }
            }
        }

        makeDirectoryToZip(new File("C:\\Users\\long\\Desktop\\file"), new File("C:\\Users\\long\\Desktop\\zip\\demo.zip"), null, 7);
        //读取要下载的文件，保存到文件输入流
        FileInputStream in = new FileInputStream("C:\\Users\\long\\Desktop\\zip\\demo.zip");
        //创建输出流
        OutputStream out = httpServletResponse.getOutputStream();
        //创建缓冲区
        byte buffer[] = new byte[1024];
        int len = 0;
        //循环将输入流中的内容读取到缓冲区当中
        while ((len = in.read(buffer)) > 0) {
            //输出缓冲区的内容到浏览器，实现文件下载
            out.write(buffer, 0, len);
        }
        //关闭文件输入流
        in.close();
        //关闭输出流
        out.close();


    }

    /**
     * 遍历目录并添加文件.
     *
     * @param jos      - JAR 输出流
     * @param file     - 目录文件名
     * @param pathName - ZIP中的目录名
     * @throws IOException
     * @throws FileNotFoundException
     */
    private void recurseFiles(ZipOutputStream jos, File file, String pathName) throws IOException, FileNotFoundException {
        byte buf[] = new byte[1024];
        if (file.isDirectory()) {
            pathName = pathName + file.getName() + "/";
            jos.putNextEntry(new ZipEntry(pathName));
            String fileNames[] = file.list();
            if (fileNames != null) {
                for (int i = 0; i < fileNames.length; i++) {
                    recurseFiles(jos, new File(file, fileNames[i]), pathName);
                }
            }
        } else {
            ZipEntry jarEntry = new ZipEntry(pathName + file.getName());
            // System.out.println(pathName + " " + file.getName());
            FileInputStream fin = new FileInputStream(file);
            BufferedInputStream in = new BufferedInputStream(fin);
            jos.putNextEntry(jarEntry);
            int len;
            while ((len = in.read(buf)) >= 0) {
                jos.write(buf, 0, len);
            }
            in.close();
            jos.closeEntry();
        }
    }

    /**
     * 创建 ZIP/JAR 文件.
     *
     * @param directory     -要添加的目录
     * @param zipFile       -保存的 ZIP 文件名
     * @param zipFolderName -ZIP 中的路径名
     * @param level         -压缩级别(0~9)
     * @throws IOException
     * @throws FileNotFoundException
     */
    public void makeDirectoryToZip(File directory, File zipFile, String zipFolderName, int level) throws IOException, FileNotFoundException {
        level = (level < 0 || level > 9) ? 7 : level;
        if (zipFolderName == null) {
            zipFolderName = "";
        }
        ZipOutputStream jos = new ZipOutputStream(new FileOutputStream(zipFile));
        jos.setLevel(level);
        String fileNames[] = directory.list();
        if (fileNames != null) {
            for (int i = 0; i < fileNames.length; i++) {
                recurseFiles(jos, new File(directory, fileNames[i]), zipFolderName);
            }
        }
        jos.close();
    }
}


